﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.GlobeCore;
using ESRI.ArcGIS.Output;

namespace ODM_Code
{
    public class rUtils
    {

        private IActiveView ruView;
        //private IMap ruMap;

        public rUtils()
        {
        }

        /// <summary>
        /// Setter for private IActiveView
        /// </summary>
        /// <param name="view"></param>
        public void SetView(IActiveView view)
        {
            ruView = view;
        }

        #region Arc Methods

        /// <summary>
        /// Cleans up the Add Data Form code by consolidating commands here
        /// </summary>
        /// <param name="inputFile">Source file to create raster from</param>
        /// <param name="eru">A rasterUtil object</param>
        /// <returns></returns>
        public IRaster AddDataFormMakeRaster(string inputFile, esriUtil.rasterUtil eru)
        {
            this.CopyPRJ(inputFile);
            IRaster ras = eru.returnRaster(inputFile);
            //ras = this.Reproject(ras);
            IRaster2 ras2 = (IRaster2)ras;
            ras2.RasterDataset.PrecalculateStats(0);
            return ras;
        }

        /// <summary>
        /// Method for saving a raster from the AddData form.
        /// </summary>
        /// <param name="ras">Raster to save</param>
        /// <param name="savePath">Raster to save</param>
        /// <param name="wks">IWorkspace to save at</param>
        public void AddDataFormSaveRaster(IRaster ras, string savePath, IWorkspace wks)
        {
            ISaveAs saver = (ISaveAs)ras;
            saver.SaveAs(savePath, wks, "TIFF");
        }

        /// <summary>
        /// Poly method for saving a raster from the AddData form. Allows setting of save type.
        /// </summary>
        /// <param name="ras">Raster to save</param>
        /// <param name="savePath">Raster to save</param>
        /// <param name="wks">IWorkspace to save at</param>
        /// <param name="type">IMG, IMAGINE Image, TIFF</param>
        public void AddDataFormSaveRaster(IRaster ras, string savePath, IWorkspace wks, string type)
        {
            ISaveAs saver = (ISaveAs)ras;
            string saveType = "";
            switch (type)
            {
                case ".tif":
                    saveType = "TIFF";
                    break;
                case ".img":
                    saveType = "IMAGINE Image";
                    break;
                default:
                    saveType = "TIFF";
                    break;
            }
            
            saver.SaveAs(savePath, wks, saveType);
        }

        /// <summary>
        /// Add a shapefile to the map.
        /// </summary>
        /// <param name="view">IActiveView of the current map view</param>
        /// <param name="pathToShapefile">Full path to the shapefile</param>
        public void AddShapefileToMap(IActiveView view, String pathToShapefile)
        {
            if (view == null)
            {
                return;
            }

            // Create a new ShapefileWorkspaceFactory CoClass to create a new workspace
            IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactoryClass();

            // IO.Path.GetDirectoryName(shapefileLocation) returns the directory part of the string. Example: "C:\test\"
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(pathToShapefile), 0); // Explicit Cast

            // IO.Path.GetFileNameWithoutExtension(shapefileLocation) returns the base filename (without extension). Example: "cities"
            IFeatureClass featureClass = featureWorkspace.OpenFeatureClass(System.IO.Path.GetFileNameWithoutExtension(pathToShapefile));

            IFeatureLayer featureLayer = new FeatureLayerClass();
            featureLayer.FeatureClass = featureClass;
            featureLayer.Name = featureClass.AliasName;
            featureLayer.Visible = true;

            ILegendInfo lInfo = (ILegendInfo)featureLayer;
            lInfo.get_LegendGroup(0).Visible = false;

            view.FocusMap.AddLayer(featureLayer);

            // Zoom the display to the full extent of all layers in the map
            view.Extent = view.FullExtent;
            view.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
        }
        
        /// <summary>
        /// Super simple method. Returns an IRasterLayer from a passed path to a raster on disk
        /// </summary>
        /// <param name="pathToRasterDataset"></param>
        /// <returns>IRasterLayer</returns>
        public IRasterLayer CreateLayerFromDisk(string pathToRasterDataset)
        {
            IRasterLayer loadLayer = new RasterLayerClass();
            loadLayer.CreateFromFilePath(pathToRasterDataset);
            return loadLayer;
        }

        public static void DumpToASCII(IRaster rasterToExport, string exportLocation, string name)
        {
            IRasterProps rp = (IRasterProps)rasterToExport;
            int ncols = rp.Width;
            int nrows = rp.Height;
            double xllcorner = rp.Extent.LowerLeft.X;
            double yllcorner = rp.Extent.LowerLeft.Y;
            IPnt pntCellsize = rp.MeanCellSize();
            object cellsize = pntCellsize.X;

            System.Array nodataary = (System.Array)rp.NoDataValue;
            object nodataval = nodataary.GetValue(0);

            rstPixelType pixelType = rp.PixelType;

            string filename = exportLocation + "\\" + name + ".txt";
            StreamWriter sw = new StreamWriter(filename);

            sw.WriteLine("ncols         " + ncols.ToString());
            sw.WriteLine("nrows         " + nrows.ToString());
            sw.WriteLine("xllcorner     " + xllcorner.ToString());
            sw.WriteLine("yllcorner     " + yllcorner.ToString());
            sw.WriteLine("cellsize      " + cellsize.ToString());
            //sw.WriteLine("NODATA_value  " + nodataval.ToString());
            sw.WriteLine("NODATA_value  " + "-9999");

            IRaster2 zRaster = (IRaster2)rasterToExport;
            IPnt pnt = new PntClass();
            pnt.SetCoords((double)ncols, (double)nrows);
            IRasterCursor zCursor = zRaster.CreateCursorEx(pnt);
            IRasterBandCollection zBands = (IRasterBandCollection)zRaster.RasterDataset;
            IPixelBlock3 zPB3 = null;

            long blockwidth = 0;
            long blockheight = 0;
            System.Array zPixels = null;

            object z;

            do
            {
                zPB3 = (IPixelBlock3)zCursor.PixelBlock;
                blockwidth = zPB3.Width;
                blockheight = zPB3.Height;
                //zPB3.Mask(rp.NoDataValue);

                zPixels = (System.Array)zPB3.get_PixelData(0);

                for (long i = 0; i < blockheight; i++)
                {
                    for (long j = 0; j < blockwidth; j++)
                    {
                        z = zPixels.GetValue(j, i);

                        if (Convert.ToDouble(z) == Convert.ToDouble(nodataval))
                        {
                            z = -9999;
                        }

                        //switch (pixelType)
                        //{
                        //    case rstPixelType.PT_DOUBLE:
                        //        break;
                        //    case rstPixelType.PT_FLOAT:
                        //        break;
                        //    case rstPixelType.PT_LONG:
                        //        break;
                        //    case rstPixelType.PT_SHORT:
                        //        break;
                        //}

                        sw.Write(z.ToString() + " ");
                    }

                    sw.Write("\n");
                }

            } while (zCursor.Next() == true);

            sw.Close();
        }
       
        /// <summary>
        /// Creates a PNG file (not georeferenced, this is only an image exporter)
        /// </summary>
        /// <param name="view">An IActiveView object of the current map</param>
        /// <param name="outPath">String representing the path the output will go to</param>
        /// <param name="rasName">String of the raster's name</param>
        /// <returns>true if successful, false if not</returns>
        /// <remarks>Only useful for KML exporting, as the filename is created relative to the KML folder location</remarks>
        public string ExportPNG(IActiveView view, string outPath, string rasName)
        {
            if (view == null)
            {
                return "";
            }

            IExport exp = new ExportPNGClass();
            IExportPNG expPNG = (IExportPNG)exp;

            rasName = rasName.Replace(" ", "_");
            rasName = rasName.Replace(",", "");
            rasName = rasName.Replace("Period ", "P");
            
            exp.ExportFileName = outPath + "\\" + rasName + ".png";

            int screenRes = 96;
            int outputRes = 300;
            exp.Resolution = outputRes;

            IColor white = new RgbColorClass();
            white.RGB = 16777215;
            expPNG.TransparentColor = white;

            ESRI.ArcGIS.esriSystem.tagRECT expRECT;
            expRECT.left = 0;
            expRECT.top = 0;
            expRECT.right = view.ExportFrame.right * (outputRes / screenRes);
            expRECT.bottom = view.ExportFrame.bottom * (outputRes / screenRes);

            // Set up the PixelBounds envelope to match the expRECT
            IEnvelope env = new EnvelopeClass();
            env.PutCoords(expRECT.left, expRECT.top, expRECT.right, expRECT.bottom);
            exp.PixelBounds = env;

            int hDC = exp.StartExporting();

            view.Output(hDC, (System.Int16)exp.Resolution, ref expRECT, null, null);
            exp.FinishExporting();
            exp.Cleanup();

            return rasName + ".png";
        }

        public string ExportPNG(IActiveView view, IRaster ras, string outPath, string rasName)
        {
            if (view == null)
            {
                return "";
            }

            IExport exp = new ExportPNGClass();
            IExportPNG expPNG = (IExportPNG)exp;

            rasName = rasName.Replace(" ", "_");
            rasName = rasName.Replace(",", "");
            rasName = rasName.Replace("Period ", "P");

            exp.ExportFileName = outPath + "\\" + rasName + ".png";

            int screenRes = 96;
            int outputRes = 300;
            exp.Resolution = outputRes;

            IColor white = new RgbColorClass();
            white.RGB = 16777215;
            expPNG.TransparentColor = white;

            ESRI.ArcGIS.esriSystem.tagRECT expRECT;
            expRECT.left = 0;
            expRECT.top = 0;
            expRECT.right = view.ExportFrame.right * (outputRes / screenRes);
            expRECT.bottom = view.ExportFrame.bottom * (outputRes / screenRes);

            IRasterProps rProp = (IRasterProps)ras;

            // IPoints representing the SCREEN POSITION of each corner of the raster
            IPoint upperLeft = GetScreenCoordinatesFromMapCoorindates(rProp.Extent.UpperLeft, ruView);
            IPoint upperRight = GetScreenCoordinatesFromMapCoorindates(rProp.Extent.UpperRight, ruView);
            IPoint lowerLeft = GetScreenCoordinatesFromMapCoorindates(rProp.Extent.LowerLeft, ruView);
            IPoint lowerRight = GetScreenCoordinatesFromMapCoorindates(rProp.Extent.LowerRight, ruView);
         

            // Set up the PixelBounds envelope to match the expRECT
            IEnvelope env = new EnvelopeClass();
            env.PutCoords(expRECT.left, expRECT.top, expRECT.right, expRECT.bottom);
            //env.PutCoords(lowerLeft.X, lowerRight.Y, upperLeft.X, upperLeft.Y);

            exp.PixelBounds = env;

            int hDC = exp.StartExporting();

            view.Output(hDC, (System.Int16)exp.Resolution, ref expRECT, null, null);
            exp.FinishExporting();
            exp.Cleanup();

            return rasName + ".png";
        }

        /// <summary>
        /// A Remap class for binary rasters.
        /// </summary>
        /// <returns></returns>
        public IRemapFilter GetFilterForBinary()
        {
            IRemapFilter rem = new RemapFilterClass();
            rem.AddClass(0.0001, 10000.0, 1);
            rem.AddClass(-10000.0, -0.0001, -1);
            rem.AddNoDataClass(0.0, 0.0);
            return rem;
        }

        /// <summary>
        /// ***INCOMPLETE***
        /// Returns the WGS1984 Lat/Long coordinates of a passed layer file.
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public List<double> GetLatLongBox(ILayer layer)
        {
            int screenRes = 96;
            int outputRes = 300;

            ESRI.ArcGIS.esriSystem.tagRECT expRECT;
            expRECT.left   = 0;
            expRECT.top    = 0;
            expRECT.right  = ruView.ExportFrame.right * (outputRes / screenRes);
            expRECT.bottom = ruView.ExportFrame.bottom * (outputRes / screenRes);

             // Set up the PixelBounds envelope to match the expRECT
            IEnvelope env = new EnvelopeClass();
            //env.SpatialReference = GetGoogleProjection();
            env.PutCoords(expRECT.left, expRECT.top, expRECT.right, expRECT.bottom);
            
            IScreenDisplay screenDisplay = ruView.ScreenDisplay;
            IDisplayTransformation displayTransformation = screenDisplay.DisplayTransformation;

            displayTransformation.TransformRect(env, ref expRECT, 0);

            ISpatialReference sr = displayTransformation.SpatialReference;

            List<double> retList = new List<double>();
            // north, south, east, west
            retList.Add(env.YMax);
            retList.Add(env.YMin);
            retList.Add(env.XMax);
            retList.Add(env.XMin);


            return retList;
        }

        public IPoint GetScreenCoordinatesFromMapCoorindates(IPoint mapPoint, IActiveView activeView)
        {
            if (mapPoint == null || mapPoint.IsEmpty || activeView == null)
            {
                return null;
            }
            IScreenDisplay screenDisplay = activeView.ScreenDisplay;
            IDisplayTransformation displayTransformation = screenDisplay.DisplayTransformation;

            System.Int32 x;
            System.Int32 y;
            displayTransformation.FromMapPoint(mapPoint, out x, out y);
            
            IPoint returnPoint = new ESRI.ArcGIS.Geometry.PointClass();
            returnPoint.PutCoords(x, y);

            return returnPoint;
        }

        /// <summary>
        /// Sets up a ISpatialReferenceFactory and returns a ISpatialReference for the 1983 Albers projection
        /// </summary>
        /// <param name="inputRaster"></param>
        /// <returns>ISpatialReference with applied projection info</returns>
        public ISpatialReference GetAlbersProjection()
        {
            // Get the path to the .prj file, located in the dll directory
            // Could change this to a prj string to reduce file clutter
            string dllPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string coordFile = dllPath + "\\res\\coord.prj";

            ISpatialReferenceFactory srFact = new SpatialReferenceEnvironmentClass();
            ISpatialReference sr = srFact.CreateESRISpatialReferenceFromPRJFile(coordFile);

            return sr;
        }

        /// <summary>
        /// Sets up a ISpatialReferenceFactory and returns a ISpatialReference for the 1984 WGS projection (Google)
        /// </summary>
        /// <param name="inputRaster"></param>
        /// <returns>ISpatialReference with applied projection info</returns>
        public ISpatialReference GetGoogleProjection()
        {
            // Get the path to the .prj file, located in the dll directory
            // Could change this to a prj string to reduce file clutter
            string dllPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string coordFile = dllPath + "\\res\\gearth.prj";

            ISpatialReferenceFactory srFact = new SpatialReferenceEnvironmentClass();
            ISpatialReference sr = srFact.CreateESRISpatialReferenceFromPRJFile(coordFile);

            return sr;
        }

        /// <summary>
        /// A remap class for arrival time rasters
        /// </summary>
        /// <returns></returns>
        public IRemapFilter GetArrivalTimeClasses()
        {
            IRemapFilter rem = new RemapFilterClass();
            rem.AddClass(-5000.0, -3000.0, -5);
            rem.AddClass(-3000.0, -2000.0, -4);
            rem.AddClass(-2000.0, -1000.0, -3);
            rem.AddClass(-1000.0, -300.0, -2);
            rem.AddClass(-300.0, 0.0, -1);

            rem.AddNoDataClass(0.0, 0.0);

            rem.AddClass(0.0, 300.0, 1);
            rem.AddClass(300.0, 1000.0, 2);
            rem.AddClass(1000.0, 2000.0, 3);
            rem.AddClass(2000.0, 3000.0, 4);
            rem.AddClass(3000.0, 5000.0, 5);

            return rem;
        }

        /// <summary>
        /// A remap class for expected loss rasters
        /// </summary>
        /// <returns></returns>
        public IRemapFilter GetExpectedLossClasses()
        {
            IRemapFilter rem = new RemapFilterClass();
            rem.AddClass(-500.0, -150.0, -5);
            rem.AddClass(-150.0, -50.0, -4);
            rem.AddClass(-50.0, -25.0, -3);
            rem.AddClass(-25.0, -10.0, -2);
            rem.AddClass(-10.0, 0.0, -1);

            rem.AddNoDataClass(0.0, 0.0);

            rem.AddClass(0.0, 10.0, 1);
            rem.AddClass(10.0, 25.0, 2);
            rem.AddClass(25.0, 50.0, 3);
            rem.AddClass(50.0, 150.0, 4);
            rem.AddClass(150.0, 500.0, 5);

            return rem;
        }

        /// <summary>
        /// A remap class for node flame length rasters
        /// </summary>
        /// <returns></returns>
        public IRemapFilter GetNodeFlamelengthClasses()
        {
            IRemapFilter rem = new RemapFilterClass();
            rem.AddClass(-50.0, -3.0, -5);
            rem.AddClass(-3.0, -1.0, -4);
            rem.AddClass(-1.0, -0.3, -3);
            rem.AddClass(-0.3, -0.05, -2);
            rem.AddClass(-0.05, 0.0, -1);

            rem.AddNoDataClass(0.0, 0.0);

            rem.AddClass(0.0, 0.05, 1);
            rem.AddClass(0.05, 0.3, 2);
            rem.AddClass(0.3, 1.0, 3);
            rem.AddClass(1.0, 3.0, 4);
            rem.AddClass(3.0, 50.0, 5);

            return rem;
        }


        /// <summary>
        /// Searches current map layers and returns the index of the first layer to
        /// match the search parameters.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="layerName"></param>
        /// <returns></returns>
        public int GetLayerIndex(IMap map, String layerName)
        {
            int mapIndex = 0;

            for (int i = 0; i <= map.LayerCount - 1; i++)
            {
                if (map.get_Layer(i).Name.Equals(layerName))
                {
                    mapIndex = i;
                }
            }

            return mapIndex;
        }

        /// <summary>
        /// **COPIED FROM GEODATABASEUTILITY**
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public IRasterRenderer ImportRasterRenderer(String path)
        {
            //Create a new GxLayer.
            ESRI.ArcGIS.Catalog.IGxLayer gxLayerCls = new ESRI.ArcGIS.Catalog.GxLayer();
            ESRI.ArcGIS.Catalog.IGxFile gxFile = (ESRI.ArcGIS.Catalog.IGxFile)gxLayerCls; //Explicit Cast.
            IRasterRenderer rend = null;

            //Set the path for where the layer file is located on disk.
            gxFile.Path = path;

            //Test if you have a valid layer and add it to the map.
            if (!(gxLayerCls.Layer == null))
            {
                IRasterLayer pRastLyr = (IRasterLayer)gxLayerCls.Layer;
                rend = pRastLyr.Renderer;
            }

            return rend;
        }

        public IRasterLayer PrepRasterForMap(IRaster ir, string layerNameForRenderer, string nameForLayer)
        {
            string dllPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

            IRasterRenderer irr = this.ImportRasterRenderer(dllPath + "\\res\\" + layerNameForRenderer);
            irr.Raster = ir;

            irr.Update();

            IRasterLayer irl = new RasterLayerClass();
            irl.CreateFromRaster(ir);
            irl.Name = nameForLayer;

            irl.Renderer = irr;
            return irl;
        }

        /// <summary>
        /// Returns an IRaster projected in the GEarth (1984 WGS) projection. Assumes input IRaster
        /// will be in the 1983 Albers projection.
        /// </summary>
        /// <param name="inRaster">IRaster to be reprojected</param>
        /// <returns>IRaster that has been reprojected</returns>
        public IRaster Reproject(IRaster inRaster)
        {
            string dllPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string coordFile = dllPath + "\\res\\gearth.prj";
            ISpatialReferenceFactory srFact = new SpatialReferenceEnvironmentClass();
            ISpatialReference sr = srFact.CreateESRISpatialReferenceFromPRJFile(coordFile);
            
            return this.ProjectRasterWithDatumTransformation(inRaster, sr);
        }

        /// <summary>
        /// Does the actual transformation used by Reproject.
        /// </summary>
        /// <param name="raster">IRaster to be reprojected</param>
        /// <param name="outSR">ISpatialReference to be projected to</param>
        /// <returns>IRaster that has been reprojected</returns>
        /// <remarks>Note that this method is hard-coded to use a 1983 Albers >> 1984 WGS projection, and as such
        /// should not be used by any method except for this.Reproject</remarks>
        protected IRaster ProjectRasterWithDatumTransformation(IRaster raster, ISpatialReference outSR)
        {
            IRasterProps rasterProps = (IRasterProps)raster;
            rasterProps.SpatialReference = outSR;

            esriSRGeoTransformation2Type geoTrans = esriSRGeoTransformation2Type.esriSRGeoTransformation_NAD_1983_To_WGS_1984_6;

            ISpatialReferenceFactory2 srFactory = new SpatialReferenceEnvironmentClass();
            IGeoTransformation geoTransformation = (IGeoTransformation)srFactory.CreateGeoTransformation((int)geoTrans);

            //Add to the geotransformation operation set.
            IGeoTransformationOperationSet operationSet = new GeoTransformationOperationSetClass();
            operationSet.Set(esriTransformDirection.esriTransformForward, geoTransformation);
            operationSet.Set(esriTransformDirection.esriTransformReverse, geoTransformation);

            //Set the geotransformation on the raster.
            IRaster2 raster2 = (IRaster2)raster;
            raster2.GeoTransformations = operationSet;

            return raster;
        }
        
        #endregion

        #region Non-Arc Methods

        /// <summary>
        /// Writes individual layers to the KML document, and exports the associated PNG
        /// </summary>
        /// <param name="writer">A StreamWriter object open and associated to the .kml file</param>
        /// <param name="rasterLayerName">The name of the raster layer as known by ArcMap</param>
        /// <param name="idNum">The layer's map index, for ID purposes</param>
        /// <returns></returns>
        public bool AddLayerToKML(StreamWriter writer, ILayer layer, string pngPath, int idNum)
        {

            if (layer == null)
            {
                return false;
            }

            string rasterLayerName = layer.Name;

            writer.WriteLine("  <GroundOverlay id=\"" + idNum + "\">");
            writer.WriteLine("    <Snippet></Snippet>");
            writer.WriteLine("    <name>" + rasterLayerName + "</name>");

            writer.WriteLine("    <Icon>");
            writer.WriteLine("      <href>" + pngPath + "</href>");
            writer.WriteLine("      <viewBoundScale>1.0</viewBoundScale>");
            writer.WriteLine("    </Icon>");

            List<double> bbox = this.GetLatLongBox(null);

            writer.WriteLine("    <LatLonBox>");
            writer.WriteLine("      <north>" + bbox[0].ToString() + "</north>");
            writer.WriteLine("      <south>" + bbox[1].ToString() + "</south>");
            writer.WriteLine("      <east>" + bbox[2].ToString() + "</east>");
            writer.WriteLine("      <west>" + bbox[3].ToString() + "</west>");
            writer.WriteLine("      <rotation>0</rotation>");
            writer.WriteLine("    </LatLonBox>");
            writer.WriteLine("  </GroundOverlay>");

            return true;
        }

        /// <summary>
        /// Checks that an analysis area has been selected.
        /// </summary>
        /// <returns></returns>
        public static Boolean CheckInit()
        {
            if (ConfigSettings.ReadSetting("initialised").Equals("true"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Check utility for user-input iteration value. Checks entered value against available results
        /// files and returns true only if a matching iteration value is found.
        /// </summary>
        /// <param name="resultsPath">Path to current results folder</param>
        /// <param name="iterationToCheck">Iteration value to check</param>
        /// <returns>True if value is found, false otherwise</returns>
        public Boolean CheckIteration(string resultsPath, int iterationToCheck)
        {
            bool validIteration = false;

            string[] files = Directory.GetFiles(resultsPath, "arrivaltime*");
            
            foreach (string f in files)
            {
                int staOfIter = resultsPath.Length + 12;
                int endOfIter = f.IndexOf("_", staOfIter);

                if (int.Parse(f.Substring(staOfIter, endOfIter - staOfIter)) == iterationToCheck)
                {
                    validIteration = true;
                    break;
                }
            }

            return validIteration;
        }

        /// <summary>
        /// Checks if the fire located within the passed results folder is a single or multiple fire scenario.
        /// </summary>
        /// <param name="resultsFolderPath"></param>
        /// <returns>True if multifire is detected, False if not.</returns>
        public Boolean CheckForMultifire(string resultsFolderPath)
        {

            Boolean multiFire = true;
            DirectoryInfo di = new DirectoryInfo(resultsFolderPath);
            string at = "arrivaltime*";
            System.IO.FileInfo[] fi2 = di.GetFiles(at);
            FileInfo test = (FileInfo)fi2.GetValue(0);
            string testName = test.Name;
            int undCount = 0;
            foreach (char c in testName)
            {
                if (c.Equals('_'))
                {
                    undCount += 1;
                }
            }

            if (undCount != 2)
            {
                multiFire = false;
            }

            ConfigSettings.WriteSetting("multiFire", "false");

            return multiFire;
        }

        /// <summary>
        /// Reads mf_scenario.dbf and determines if passed alternative is a Z-Run or not. Mostly used
        /// for grey-ing out options on the Add Data form
        /// </summary>
        /// <param name="selectedAlternative">The contents of the alternative selection box</param>
        /// <returns>True if Z-run, False if not</returns>
        public Boolean CheckForZRun(string selectedAlternative)
        {
            bool isZRun = false;

            string shortName = selectedAlternative.Substring(1, selectedAlternative.IndexOf("_") - 1);

            string pathToMFScenario = "C:\\magfire\\" + ConfigSettings.ReadSetting("analysisArea") + "\\mf_scenario.dbf";
            string provider = "Provider=VFPOLEDB.1";
            string dataSrc = "data source=" + pathToMFScenario;
            string conStr = provider + ";" + dataSrc + ";";
            string selectBase = "SELECT * FROM mf_scenario";

            DataSet ds = new DataSet();
            DataTable dt = null;
            try
            {
                OleDbConnection cnxnMF = new OleDbConnection(conStr);

                OleDbCommand currCmd = new OleDbCommand(selectBase, cnxnMF);
                OleDbDataAdapter currAdapter = new OleDbDataAdapter(currCmd);

                currAdapter.Fill(ds);
                dt = ds.Tables["Table"];

                cnxnMF.Close();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Could not populate mf_scenario datatable.\n" + ex.Message, "mf_scenario Read Error");
                System.Diagnostics.Trace.WriteLine(ex.Message, "CheckForZRun TableOpen");
                throw;
            }

            try
            {
                string expr = "Prob_code = " + shortName;
                DataRow[] selRow = dt.Select(expr);

                if (selRow[0]["Intensity"].Equals("Z"))
                {
                    isZRun = true;
                }
            }
            catch (IndexOutOfRangeException iex)
            {
                System.Diagnostics.Trace.WriteLine(iex.Message, "CheckForZRun IOOR");
                throw new IndexOutOfRangeException();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "CheckForZRun RowRead");
                throw;
            }

            //MessageBox.Show(isZRun.ToString(), "isZRun");
            return isZRun;
        }

        /// <summary>
        /// Writes the config setting "FireCount", which represents the highest fire value found
        /// in the results path.
        /// </summary>
        /// <param name="resultsFolderPath">Full path to the results folder, e.g.: C:\magfire\DBF\input\SCENARIO\results</param>
        /// <remarks>CheckMultifireBounds does not return a value. Access the found fire count through the 
        /// ConfigSettings/appSettings/FireCount attribute.</remarks>
        public int CheckMultifireBounds(string resultsFolderPath)
        {
            int fireCount = 0;
            DirectoryInfo di = new DirectoryInfo(resultsFolderPath);
            string at = "arrivaltime*";
            System.IO.FileInfo[] fi2 = di.GetFiles(at);

            List<int> fires = new List<int>();

            foreach (FileInfo fi in fi2)
            {
                if (fi.Name.EndsWith(".txt"))
                {
                    int startIndex = fi.Name.IndexOf("_");
                    string fireNum = fi.Name.Substring(startIndex + 1, 1);
                    fires.Add(int.Parse(fireNum));
                }
            }

            foreach (int i in fires)
            {
                if (i > fireCount)
                {
                    fireCount = i;
                }
            }

            //ConfigSettings.WriteSetting("FireCount", fireCount.ToString());
            return fireCount;
        }

        /// <summary>
        /// Writes the config setting "PeriodCount", which represents the highest period value found
        /// in the results path.
        /// </summary>
        /// <param name="resultsFolderPath">Full path to the results folder, e.g.: C:\magfire\DBF\input\SCENARIO\results</param>
        /// <remarks>CheckPeriodBounds does not return a value. Access the found period count through the 
        /// ConfigSettings/appSettings/PeriodCount attribute.</remarks>
        public int CheckPeriodBounds(string resultsFolderPath)
        {
            int periodCount = 0;
            DirectoryInfo di = new DirectoryInfo(resultsFolderPath);
            string at = "arrivaltime*";
            System.IO.FileInfo[] fi2 = di.GetFiles(at);

            List<int> periods = new List<int>();

            foreach (FileInfo fi in fi2)
            {
                if (fi.Name.EndsWith(".txt"))
                {
                    int startIndex = fi.Name.IndexOf("_");
                    string periodNum = fi.Name.Substring(startIndex + 3, 1);
                    periods.Add(int.Parse(periodNum));
                }
            }

            foreach (int i in periods)
            {
                if (i > periodCount)
                {
                    periodCount = i;
                }
            }

            //ConfigSettings.WriteSetting("PeriodCount", periodCount.ToString());
            return periodCount;
        }

        /// <summary>
        /// Deletes anything found in the C:\\magfire\\temp directory
        /// </summary>
        public void ClearTemp()
        {
            string tempPath = "C:\\magfire\\temp";
            string[] files = Directory.GetFiles(tempPath);
            foreach (string f in files)
            {
                File.Delete(f);
            }
        }

        /// <summary>
        /// Copies the 1983 Albers projection file to a file of the same name as the passed
        /// string (see param). This allows the returnRaster function (from esriUtil) to import
        /// the ASCII with associated projection information.
        /// </summary>
        /// <param name="nameOfTxt">String of the full path to associated text file.</param>
        public void CopyPRJ(string nameOfTxt)
        {
            string dllPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string coordFile = dllPath + "\\res\\coord.prj";
            string shortName = nameOfTxt.Substring(0, (nameOfTxt.Length - 4));
            string newPRJFile = shortName + ".prj";

            if (File.Exists(coordFile) && !File.Exists(newPRJFile))
            {
                File.Copy(coordFile, newPRJFile);
            }
        }

        /// <summary>
        /// Detects the number of fires in the passed alternative by counting 
        /// "inputfileN.asc" files
        /// </summary>
        /// <param name="alternativePath">Path of alternative to check</param>
        /// <returns>Number of fires</returns>
        public int CountFires(string alternativePath)
        {
            int numFires = 0;

            string[] inputFiles = Directory.GetFiles(alternativePath, "inputfile*");
            numFires = inputFiles.Length;

            return numFires;
        }

        /// <summary>
        /// Sets up the output rasters for treatment schedule. This includes the treatment period raster,
        /// the treatment type raster. Also sets symbology for each of the rasters.
        /// </summary>
        /// <param name="resultsFolderPath">String of the results folder path. Ex: C:/magfire/DBF/Scenario/Results</param>
        /// <param name="isPeriod">True if period, False if regime</param>
        /// <param name="treatAry">A 2D array containing the treatment value for each cell</param>
        /// <remarks>Reads the treatgrid.txt file, then uses it as a control for iteration. Writes each pixel
        /// to created TR_period.txt or TR_regime.txt files.</remarks>
        protected void CreateTreatSchedRasters(String resultsFolderPath, Boolean isPeriod, int[,] treatArray)
        {
            StreamReader sr = new StreamReader("C:\\magfire\\" + ConfigSettings.ReadSetting("analysisArea") + "\\input\\treatgrid.txt");
            StreamWriter sw;

            string mess;
            if (isPeriod)
            {
                mess = "Writing treatment schedule period raster.";
            }
            else
            {
                mess = "Writing treatment schedule regime raster.";
            }

            ODM_Code.Forms.ProgressForm pf = new ODM_Code.Forms.ProgressForm(mess, 1, (treatArray.GetLength(0) * treatArray.GetLength(1)), 1);
            //ODM_Code.Forms.ProgressForm pf = new ODM_Code.Forms.ProgressForm(mess, 1, (treatArray.GetLength(0)), 1);
            pf.Show();
            pf.Activate();
            pf.BringToFront();

            if (isPeriod)
            {
                sw = new StreamWriter(resultsFolderPath + "\\TR_period.txt");
            }
            else
            {
                sw = new StreamWriter(resultsFolderPath + "\\TR_regime.txt");
            }

            string line;

            // nCols
            line = sr.ReadLine();
            sw.WriteLine(line);
            pf.SetProgressLabel(line);
            // nRows
            line = sr.ReadLine();
            sw.WriteLine(line);
            pf.SetProgressLabel(line);
            // xllcorner
            line = sr.ReadLine();
            sw.WriteLine(line);
            pf.SetProgressLabel(line);
            // y11corner
            line = sr.ReadLine();
            sw.WriteLine(line);
            pf.SetProgressLabel(line);
            // cellsize
            line = sr.ReadLine();
            sw.WriteLine(line);
            pf.SetProgressLabel(line);

            // NODATA_value
            line = "NODATA_value\t 0";
            sw.WriteLine(line);
            pf.SetProgressLabel(line);

            sr.Close();

            pf.SetProgressLabel(mess);
            string mainmess = mess;

            for (int row = 0; row < treatArray.GetLength(0); row++)
            {
                for (int col = 0; col < treatArray.GetLength(1); col++)
                {
                    sw.Write(treatArray[row, col].ToString());
                    if (col + 1 != treatArray.GetLength(1))
                    {
                        sw.Write(" ");
                    }
                    if (col + 1 == treatArray.GetLength(1))
                    {
                        sw.Write("\n");
                    }
                    pf.StepBar();
                }
                mess = mainmess + "\nRow: " + row.ToString();
                pf.SetProgressLabel(mess);
                //pf.Refresh();
                //pf.StepBar();
            }

            pf.Close();
            sw.Close();
        }

        /// <summary>
        /// Returns the iteration number of the best treatment found.
        /// </summary>
        /// <param name="resultsFolderPath">String with the full path to the results folder.  ex: C://MagFire//DBF_LT_West//ScenarioName//input//results</param>
        /// <returns>an int value of the best found solution</returns>
        /// <remarks>Reads the SimulatedAnnealing.txt file and uses the lowest total expected loss as the 'best' solution.</remarks>
        public int GetBestSolutionNum(string resultsFolderPath)
        {
            try
            {
                if (Directory.Exists(resultsFolderPath))
                {
                    StreamReader fr = new StreamReader(resultsFolderPath + "\\SimulatedAnnealing.txt");
                    string line = fr.ReadLine();  // Advance reader to first line of data
                    //List<double> vals = new List<double>();

                    double bestTr = 10000000.0;
                    int bestTrIndex = 0;

                    while (!fr.EndOfStream)
                    {
                        line = fr.ReadLine();
                        if (line.Length > 1)
                        {
                            string[] lineSplit = line.Split('\t');
                            double currTreat = Double.Parse(lineSplit[1]);

                            if (bestTr > currTreat)
                            {
                                bestTr = currTreat;
                                bestTrIndex = int.Parse(lineSplit[0]);
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                    fr.Close();
                    return bestTrIndex;
                }
                else
                {
                    return 0;
                }
            }
            catch (IndexOutOfRangeException iex)
            {
                string mess = "\nIndex not found, probably due to a SimulatedAnnealing.txt\nfile read eror. Cancelling function.";
                MessageBox.Show(iex.Message + mess, "GetBestSolution Index Error");
                System.Diagnostics.Trace.WriteLine(iex.Message, "GetBestSolution Index Error");
                return 0;
            }
            catch (IOException flex)
            {
                string mess = "The selected scenario seems to be running and/or the interface cannot\naccess the SimulatedAnnealing.txt file. If adding data from OptFuels\nresults, try manually entering an iteration to load.";
                MessageBox.Show(mess, "Best Solution File Load Error");
                System.Diagnostics.Trace.WriteLine(flex.Message);
                //throw new FileLoadException("File in use.", resultsFolderPath + "\\SimulatedAnnealing.txt");
                throw;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString() + "\n" + ex.Message, "GetBestSolution Error");
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetBestSolution Error");
                throw;
            }

        }

        /// <summary>
        /// Writes a text file in the gis results directory which shows the management codes next to their names.
        /// </summary>
        /// <param name="pathTo43b">Full path to table _43b.DBF</param>
        /// <param name="resultsPath">Path to results foder, e.g. C:\Magfire\DBF\INPUT\SCENARIO\results</param>
        public void GetRegimeValues(string pathTo43b, string resultsPath)
        {
            string provider = "Provider=VFPOLEDB.1";
            string dataSrc = "data source=" + pathTo43b;
            string conStr = provider + ";" + dataSrc + ";";
            string selectBase = "SELECT * FROM _43b";

            StreamWriter sw = new StreamWriter(resultsPath + "\\gis\\RegimeCodes.txt");
            sw.WriteLine("Value\tName");

            DataSet ds = new DataSet();
            DataTable dt = null;
            try
            {
                OleDbConnection cnxn43 = new OleDbConnection(conStr);
                
                OleDbCommand currCmd = new OleDbCommand(selectBase, cnxn43);
                OleDbDataAdapter currAdapter = new OleDbDataAdapter(currCmd);

                currAdapter.Fill(ds);
                dt = ds.Tables["Table"];
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Could not populate management regime datatable.\n" + ex.Message, "_43b Read Error");
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetRegimeValues");
            }

            try
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    DataRow dr = dt.Rows[i];
                    sw.WriteLine(dr[2].ToString() + "\t" + dr[1]);
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Error writing RegimeCodes.txt\n" + ex.Message, "GetRegimeValues Error");
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetRegimeValues");
            }
            sw.Close();
        }

        /// <summary>
        /// Reads the inputfile#.asc to determine the path of the ignition shapefile.
        /// </summary>
        /// <param name="scenario"></param>
        /// <param name="fireNum">String representing the fire number. (1 for single-fire scenarios) </param>
        /// <returns>string of the path to the ignition file</returns>
        public String GetIgnitionFilePath(string scenario, string fireNum)
        {
            string pathToIgnitionFile = "";

            try
            {
                string inputFile = "C:\\magfire\\" + ConfigSettings.ReadSetting("analysisArea") + "\\input\\" + scenario + "\\inputfile" + fireNum + ".asc";
                StreamReader sr = new StreamReader(inputFile);
                string line = "";

                while (!sr.EndOfStream)
                {
                    line = sr.ReadLine();
                    if (line.StartsWith("MTT_IGNITION_FILE"))
                    {
                        pathToIgnitionFile = line.Substring(19);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetIgnitionFilePath");
                throw;
            }

            //MessageBox.Show(pathToIgnitionFile, "Ignition File Path");
            return pathToIgnitionFile;
        }

        public String GetIgnitionFilePath(string pathToInputFile)
        {
            string pathToIgnitionFile = "";

            try
            {
                string inputFile = pathToInputFile;
                StreamReader sr = new StreamReader(inputFile);
                string line = "";

                while (!sr.EndOfStream)
                {
                    line = sr.ReadLine();
                    if (line.StartsWith("MTT_IGNITION_FILE"))
                    {
                        pathToIgnitionFile = line.Substring(19);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetIgnitionFilePath");
                throw;
            }

            //MessageBox.Show(pathToIgnitionFile, "Ignition File Path");
            return pathToIgnitionFile;
        }

        /// <summary>
        /// Returns a 2D array representation of the treatgrid.txt file, for referencing cutting unit locations
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        protected int[,] GetTreatGrid()
        {
            StreamReader sr = new StreamReader("C:\\magfire\\" + ConfigSettings.ReadSetting("analysisArea") + "\\input\\treatgrid.txt");
            string line;

            

            line = sr.ReadLine();
            int cols = int.Parse(line.Substring(line.LastIndexOf(" ")));

            line = sr.ReadLine();
            int rows = int.Parse(line.Substring(line.LastIndexOf(" ")));

            string mess = "Loading treatgrid.txt";
            ODM_Code.Forms.ProgressForm pf = new ODM_Code.Forms.ProgressForm(mess, 1, (cols * rows), 1);
            pf.Show();
            pf.Activate();
            pf.BringToFront();
            pf.SetProgressLabel(mess);

            int[,] cuLocs = new int[rows, cols];

            string[] lineSplit;

            line = sr.ReadLine();
            line = sr.ReadLine();
            line = sr.ReadLine();
            line = sr.ReadLine();

            try
            {
                for (int rowCount = 0; rowCount < rows; rowCount++)
                {

                    line = sr.ReadLine();
                    lineSplit = line.Split(' ');

                    for (int colCount = 0; colCount < cols; colCount++)
                    {
                        //MessageBox.Show("[" + (rowCount).ToString() + "," + colCount.ToString() + "] = " + lineSplit[j]);
                        cuLocs[rowCount, colCount] = int.Parse(lineSplit[colCount]);
                        pf.StepBar();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception in getTreatGrid");
                System.Diagnostics.Trace.WriteLine(ex.Message, "GetTreatGrid");
            }

            pf.Close();
            sr.Close();
            return cuLocs;
        }

        /// <summary>
        /// Reads the Int_Prj_Id_# file, where # is the best found treatment.  Then, creates 2 new rasters for treatment period and treatment type
        /// </summary>
        /// <param name="resultsFolder">String of path to results folder</param>
        /// <param name="bestSolutionNum">Int of best found solution iteration</param>
        /// <param name="isPeriod">True if using for period raster, False if using for regime raster</param>
        /// <returns></returns>
        public bool IntPrjIdLookup(string resultsFolder, int bestSolutionNum, Boolean isPeriod)
        {
            bool success = false;
            string provider = "Provider=VFPOLEDB.1";
            string dataSrc = "data source=" + "C:\\magfire\\" + ConfigSettings.ReadSetting("analysisArea") + "\\input\\_54.DBF";
            string conStr = provider + ";" + dataSrc + ";";
            string selectBase = "SELECT * FROM _54";

            //rUtils ru = new rUtils();

            Dictionary<int, int> outIntRP = this.LoadOutIntRP(resultsFolder, bestSolutionNum);
            int[,] cuLocs = this.GetTreatGrid();

            int[,] treatAry = new int[cuLocs.GetLength(0), cuLocs.GetLength(1)];

            ODM_Code.Forms.ProgressForm pf = new Forms.ProgressForm("IntProjIDLookup Progress", 1, outIntRP.Count, 1);
            //pf.ShowDialog();
            pf.Show();
            pf.Activate();
            pf.BringToFront();

            string mess;
            if (isPeriod)
            {
                mess = "Reading treatment schedule period values.";
            }
            else
            {
                mess = "Reading treatment schedule regime values.";
            }
            pf.SetProgressLabel(mess);
            string mainmess = mess;

            try
            {
                OleDbConnection cnxn54 = new OleDbConnection(conStr);

                // Create new dataset for query
                DataSet ds = new DataSet();

                // Set up a command and an adapter to grab the data
                OleDbCommand currCmd = new OleDbCommand(selectBase, cnxn54);
                OleDbDataAdapter currAdapter = new OleDbDataAdapter(currCmd);

                // Fill the new dataset with queried data
                currAdapter.Fill(ds);
                //MessageBox.Show(ds.Tables["Table"].Rows.Count.ToString());

                DataTable dt = ds.Tables["Table"];

                foreach (int cutUnit in outIntRP.Keys)
                {
                    //pf.SetProgressLabel("Loading cutting unit " + cutUnit.ToString());

                    // Get the int_prj_id from the dictionary
                    int int_prj_id = outIntRP[cutUnit];

                    string expr = "Int_prj_id = " + int_prj_id.ToString();
                    DataRow[] selRow = dt.Select(expr);

                    for (int rowCount = 0; rowCount < cuLocs.GetLength(0); rowCount++)
                    {
                        for (int colCount = 0; colCount < cuLocs.GetLength(1); colCount++)
                        {
                            if (cuLocs[rowCount, colCount] == cutUnit)
                            {
                                if (isPeriod)
                                {
                                    if (int.Parse(selRow[0]["Comp2"].ToString()) != 164)
                                    {
                                        treatAry[rowCount, colCount] = int.Parse(selRow[0]["Comp5"].ToString());
                                    }
                                    else
                                    {
                                        treatAry[rowCount, colCount] = 0;
                                    }
                                }
                                else
                                {
                                    treatAry[rowCount, colCount] = int.Parse(selRow[0]["Comp2"].ToString());
                                }
                            }

                        }
                    }

                    //mess = mainmess + "\nCutting Unit: " + cutUnit.ToString();
                    //pf.SetProgressLabel(mess);
                    //pf.Refresh();
                    pf.StepBar();
                    System.Threading.Thread.CurrentThread.Join(0);  // Keep the thread from deadlocking
                }

                pf.Close();

                try
                {
                    if (isPeriod)
                    {
                        this.CreateTreatSchedRasters(resultsFolder, true, treatAry);
                    }
                    else
                    {
                        this.CreateTreatSchedRasters(resultsFolder, false, treatAry);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Exception in createTreatSchedRasters");
                    System.Diagnostics.Trace.WriteLine(ex.Message, "Unable to create schedule rasters");
                    throw;
                }

                success = true;
                cnxn54.Close();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception in intPrjId_Lookup");
                System.Diagnostics.Trace.WriteLine(ex.Message, "intPrjId_Lookup");
                throw;
            }


            return success;
        }
        
        /// <summary>
        /// Loads the Out_Int_RP_# file, where # is the passed 'bestSolutionNum'.
        /// </summary>
        /// <param name="resultsFolderPath">String with the full path to the results folder.  ex: C://MagFire//DBF_LT_West//ScenarioName//input//results</param>
        /// <param name="bestSolutionNum">Int of the best solution</param>
        /// <returns>Dictionary(int, int) of the Out_Int_RP file, where the key=cut_unit, and value=int_prj_id</returns>
        /// <remarks>Best solution number can be found using the getBestSolutionNum2 method.</remarks>
        protected Dictionary<int, int> LoadOutIntRP(string resultsFolderPath, int bestSolutionNum)
        {
            // treatmentDic holds <cutting unit id, 
            Dictionary<int, int> outIntDic = new Dictionary<int, int>();

            StreamReader fr = new StreamReader(resultsFolderPath + "\\Out_Int_RP_" + bestSolutionNum.ToString() + ".txt");
            string line = fr.ReadLine();  // Advance reader to first line of data

            try
            {
                while (!fr.EndOfStream)
                {
                    line = fr.ReadLine();
                    if (line.Length <= 1)
                    {
                        break;
                    }
                    string[] lineSplit = line.Split('\t');

                    int cut_un_id = int.Parse(lineSplit[0]);
                    int int_prj_id = int.Parse(lineSplit[2]);

                    if (cut_un_id != 0)
                    {
                        outIntDic.Add(cut_un_id, int_prj_id);
                    }
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }

            fr.Close();
            return outIntDic;
        }

        public static string RoundDoubleForView(double number)
        {
            double tempNum = Math.Round(number, 4);
            return tempNum.ToString();
        }

        #endregion

        #region Meta Report methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbfPath"></param>
        /// <param name="resultsPath"></param>
        /// <param name="scenNum"></param>
        /// <returns></returns>
        public string[] Meta_getMainInfo(string dbfPath, string resultsPath, int scenNum)
        {
            int bestSol = 0;

            try
            {
                bestSol = this.GetBestSolutionNum(resultsPath);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "Meta BestSol Query");
                MessageBox.Show("Error finding best iteration.\n\nMessage: " + ex.Message, "Best Iteration Error");
            }

            string provider = "Provider=VFPOLEDB.1";
            string dataSrc = "data source=" + dbfPath + "\\mf_scenario.DBF";
            string conStr = provider + ";" + dataSrc + ";";
            string selectBase = "SELECT * FROM mf_scenario";

            try
            {
                // Set up a command and an adapter to grab the data
                OleDbConnection cnxn = new OleDbConnection(conStr);
                OleDbCommand currCmd = new OleDbCommand(selectBase, cnxn);
                OleDbDataAdapter currAdapter = new OleDbDataAdapter(currCmd);

                // Create new dataset for query
                DataSet ds = new DataSet();

                // Fill the new dataset with queried data
                currAdapter.Fill(ds);

                // Load the table
                DataTable dt = ds.Tables["Table"];

                // Write the selection string
                string expr = "Prob_code = " + scenNum.ToString();

                // Select only the rows applicable to this scenario
                DataRow[] dr = dt.Select(expr);

                string altName = dr[0][0].ToString();
                string solvOpt = dr[0][14].ToString();
                string clustSize = dr[0][7].ToString();

                cnxn.Close();

                string naExpLoss = this.Meta_getNoActionExpLoss(resultsPath);
                naExpLoss = this.Meta_truncate(naExpLoss);
                string trExpLoss = this.Meta_getTreatmentExpLoss(resultsPath, bestSol);
                trExpLoss = this.Meta_truncate(trExpLoss);

                string[] retStr = { altName, solvOpt, clustSize, naExpLoss, trExpLoss, bestSol.ToString() };
                return retStr;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "MF_SCENARIO Read");
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inString"></param>
        /// <returns></returns>
        private string Meta_truncate(string inString)
        {
            int len = inString.Length;
            int decPos = inString.IndexOf(".");
            int diff = len - decPos;

            string retStr = null;

            if (diff < 2)
            {
                retStr = inString;
            }
            else 
            {
                retStr = inString.Substring(0, decPos + 3);
            }

            return retStr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="resultsPath"></param>
        /// <returns></returns>
        private string Meta_getNoActionExpLoss(string resultsPath)
        {
            StreamReader simReader = new StreamReader(resultsPath + "\\SimulatedAnnealing.txt");
            simReader.ReadLine();

            string line = simReader.ReadLine();
            string[] split = line.Split('\t');

            simReader.Close();

            return split[1];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="resultsPath"></param>
        /// <param name="iteration"></param>
        /// <returns></returns>
        private string Meta_getTreatmentExpLoss(string resultsPath, int iteration)
        {
            StreamReader simReader = new StreamReader(resultsPath + "\\SimulatedAnnealing.txt");
            simReader.ReadLine();

            string line;
            string[] split;
            string iter = iteration.ToString();
            string expLoss = "";

            while (!simReader.EndOfStream)
            {
                line = simReader.ReadLine();
                split = line.Split('\t');
                if (split[0].Equals(iter))
                {
                    expLoss = split[1];
                    break;
                }
            }
            
            simReader.Close();
            return expLoss;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbfPath"></param>
        /// <param name="scenNum"></param>
        /// <returns></returns>
        public Dictionary<int, string[]> Meta_getFireScenInfo(string dbfPath, int scenNum)
        {
            string provider = "Provider=VFPOLEDB.1";
            string dataSrc = "data source=" + dbfPath + "\\mf_firescenario.DBF";
            string conStr = provider + ";" + dataSrc + ";";
            string selectBase = "SELECT * FROM mf_firescenario";

            try
            {
                // Set up a command and an adapter to grab the data
                OleDbConnection cnxn = new OleDbConnection(conStr);
                OleDbCommand currCmd = new OleDbCommand(selectBase, cnxn);
                OleDbDataAdapter currAdapter = new OleDbDataAdapter(currCmd);

                // Create new dataset for query
                DataSet ds = new DataSet();

                // Fill the new dataset with queried data
                currAdapter.Fill(ds);

                // Load the table
                DataTable dt = ds.Tables["Table"];

                // Write the selection string
                string expr = "Prob_code = " + scenNum.ToString();

                // Select only the rows applicable to this scenario
                DataRow[] dr = dt.Select(expr);

                // Return dictionary
                Dictionary<int, string[]> retDict = new Dictionary<int, string[]>();

                foreach (DataRow d in dr)
                {
                    int fireScenarioNum = (int)d[1];
                    string description = d[2].ToString();
                    string fmsFile = d[3].ToString();
                    string windSpeed = d[5].ToString();
                    string windDirec = d[6].ToString();
                    string ignFile = d[9].ToString();
                    string foilMoist = d[10].ToString();
                    string weight = d[30].ToString();

                    string[] obAry = { weight, description, ignFile, fmsFile, windSpeed, windDirec, foilMoist };

                    retDict.Add(fireScenarioNum, obAry);
                }

                cnxn.Close();
                return retDict;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message, "MF_FIRESCENARIO Read");
                return null;
            }

            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alternativePath"></param>
        /// <returns></returns>
        public List<string> Meta_getAreaConstraints(string alternativePath)
        {
            StreamReader sr = new StreamReader(alternativePath + "\\constraints.txt");
            string line = sr.ReadLine();
            List<string> retList = new List<string>();

            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
                string[] spl = line.Split('\t');
                if (spl[1].StartsWith("AC_"))
                {
                    line = spl[1] + "\t" + this.Meta_truncate(spl[2]) + "\t" + this.Meta_truncate(spl[3]) + "\t" + spl[4] + "\t" + spl[6];
                    retList.Add(line);
                }
                
            }

            sr.Close();

            return retList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alternativePath"></param>
        /// <returns></returns>
        public List<string> Meta_getCostConstraints(string alternativePath)
        {
            StreamReader sr = new StreamReader(alternativePath + "\\constraints.txt");
            string line = sr.ReadLine();
            List<string> retList = new List<string>();

            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
                string[] spl = line.Split('\t');
                if (!spl[1].StartsWith("AC_"))
                {
                    line = spl[1] + "\t" + this.Meta_truncate(spl[2]) + "\t" + this.Meta_truncate(spl[3]) + "\t" + spl[4];
                    retList.Add(line);
                }
                
            }

            sr.Close();

            return retList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alternativePath"></param>
        /// <returns></returns>
        public List<string> Meta_getCostAmounts(string alternativePath)
        {
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gisPath"></param>
        /// <returns></returns>
        public Dictionary<string, double[]> Meta_calcAreaTreated(string gisPath)
        {
            esriUtil.rasterUtil jru = new esriUtil.rasterUtil();

            int periodCount = int.Parse(ConfigSettings.ReadSetting("PeriodCount"));

            string treatPeriodFile = gisPath + "\\treatPeriod.tif";
            string treatRegimeFile = gisPath + "\\treatRegime.tif";
            IRaster fullPerRas = jru.returnRaster(treatPeriodFile);
            IRaster fullRegRas = jru.returnRaster(treatRegimeFile);

            for (int i = 1; i <= periodCount; i++)
            {
                IRaster filterForThisPeriod = jru.calcEqualFunction(treatPeriodFile, i);
                //IRaster conSelect = jru.con
            }

            return null;
        }

        
        #endregion

        #region GEarth Methods

        public void ExportWorker(ILayer pLayer)
        {
            IDataset ds = (IDataset)pLayer;
            string wrkPath = ds.Workspace.PathName;
            string gEarthOutPath = wrkPath.Substring(0, wrkPath.LastIndexOf("\\")) + "gEarth";
            string saveName = gEarthOutPath + "\\" + ds.Name;

            if (!Directory.Exists(gEarthOutPath))
            {
                Directory.CreateDirectory(gEarthOutPath);
            }

            pLayer.Visible = true;
            this.ExportToKML(pLayer, gEarthOutPath, ds.Name);
            pLayer.Visible = false;
        }

        public void ExportWorker(ILayer pLayer, string gEarthOutPath)
        {
            IDataset ds = (IDataset)pLayer;
            if (!Directory.Exists(gEarthOutPath))
            {
                Directory.CreateDirectory(gEarthOutPath);
            }
            pLayer.Visible = true;
            this.ExportToKML(pLayer, gEarthOutPath, ds.Name);
            pLayer.Visible = false;
        }

        /// <summary>
        /// KML Exporter. Exports a single layer to a single .kmz file.
        /// </summary>
        /// <param name="layer">ILayer to export</param>
        /// <param name="outPath">Path to output directory</param>
        /// <remarks>The name is auto-generated from the layer's name property, so only
        /// the output directory is required.</remarks>
        public void ExportToKML(ILayer layer, string outPath)
        {
            IKmlConversion kmlCon = new KmlConvertorClass();
            IKmlConvertor gkmlCon = (IKmlConvertor)kmlCon;
            IQueryFilter qf = new QueryFilterClass();
            IPropertySet ps = new PropertySetClass();

            string layerName = layer.Name;
            layerName = layerName.Replace(" ", "_");
            layerName = layerName.Replace(",", "");
            layerName = outPath + "\\" + layerName + ".kmz";

            //ps = gkmlCon.KmlParameters;
            //ps.SetProperty("color", "8xaffffff");

            //object nams;
            //object vals;
            //ps.GetAllProperties(out nams, out vals);

            //object[] nameAry = (object[])nams;
            //object[] valsAry = (object[])vals;

            //string mess = "";
            //for (int i = 0; i < nameAry.Length; i++)
            //{
            //    string name = nameAry[i].ToString();
            //    string value = valsAry[i].ToString();
            //    string tempMess = name + " :: " + value;
            //    mess += tempMess + "\r\n";
            //}

            //MessageBox.Show(mess, "KML Properties");

            kmlCon.LayerToFile(layer, qf, ps, layerName);
        }

        /// <summary>
        /// KML Exporter. Exports a single layer to a single .kmz file. Allows manual
        /// setting of name (to use the layer name, leave out the "name" paramater).
        /// </summary>
        /// <param name="layer">ILayer to export</param>
        /// <param name="outPath">Path to output directory</param>
        /// <param name="name">Name for .kmz</param>
        public void ExportToKML(ILayer layer, string outPath, string name)
        {
            if (!Directory.Exists(outPath))
            {
                Directory.CreateDirectory(outPath);
            }

            IKmlConversion kmlCon = new KmlConvertorClass();
            IKmlConvertor gkmlCon = (IKmlConvertor)kmlCon;
            IQueryFilter qf = new QueryFilterClass();
            IPropertySet ps = new PropertySetClass();

            string layerName = name;
            layerName = layerName.Replace(" ", "_");
            layerName = layerName.Replace(",", "");
            layerName = layerName.Replace(":", "");
            layerName = outPath + "\\" + layerName + ".kmz";

            layer.Visible = true;
            kmlCon.LayerToFile(layer, qf, ps, layerName);
            layer.Visible = false;
        }

        #endregion

        #region esriUtil Methods

        #endregion

    }
}
